import Connectable::*;
import GetPut::*;
import ClientServer::*;

`include "asim/provides/librl_bsv_storage.bsh"

typedef SCOREBOARD_FIFO_ENTRY_ID#(t) CBUFFToken#(type t);

interface CBUFF #(numeric type n, type element_type);
   interface Get#(CBUFFToken#(n)) reserve;
   interface Put#(Tuple2 #(CBUFFToken#(n), element_type)) complete;
   interface Get#(element_type) drain;
endinterface

module mkCBUFF(CBUFF#(n, element_type))
   provisos(Bits#(element_type,a__));
   
   SCOREBOARD_FIFOF#(n,element_type) cbuff <- mkScoreboardFIFOF();

   let res = interface Get;
		method ActionValue#(CBUFFToken#(n)) get();
		   let tok <- cbuff.enq();
		   return tok;
		endmethod
	     endinterface;
   
   let comp = interface Put;
		 method Action put(Tuple2#(CBUFFToken#(n),element_type) t);
		    cbuff.setValue(tpl_1(t), tpl_2(t));
		 endmethod
	      endinterface;
   
   let dr = interface Get;
	       method ActionValue#(element_type) get();
		  cbuff.deq();
		  return cbuff.first();
	       endmethod
	    endinterface;

   interface Get reserve = res;
   interface Put complete = comp;
   interface Get drain = dr;

endmodule